﻿///
/// @file IRGenerator.h
/// @brief AST遍历产生线性IR的头文件
/// @author zenglj (zenglj@live.com)
/// @version 1.1
/// @date 2024-11-23
///
/// @copyright Copyright (c) 2024
///
/// @par 修改日志:
/// <table>
/// <tr><th>Date       <th>Version <th>Author  <th>Description
/// <tr><td>2024-09-29 <td>1.0     <td>zenglj  <td>新建
/// <tr><td>2024-11-23 <td>1.1     <td>zenglj  <td>表达式版增强
/// </table>
///
#pragma once

#include <unordered_map>
#include <vector>

#include "AST.h"
#include "Module.h"
#include "Instructions/LabelInstruction.h"
#include "Instructions/SingleInstruction.h"
#include "Values/ConstInt.h"
#include "PointerType.h"
#include "ZeroSetInstruction.h"
/// @brief AST遍历产生线性IR类
class IRGenerator {

public:
    /// @brief 构造函数
    /// @param root
    /// @param _module
    IRGenerator(ast_node * root, Module * _module);

    /// @brief 析构函数
    ~IRGenerator() = default;

    /// @brief 运行产生IR
    bool run();

    Value * process_expression_with_negation(ast_node * exprNode)
    {
        if (!exprNode)
            return nullptr;

        if (exprNode->node_type == ast_operator_type::AST_OP_UNARY_MINUS) {
            ast_node * child = exprNode->sons[0];
            if (!ir_visit_ast_node(child)) {
                return nullptr;
            }

            // 如果是常量，生成负常量
            if (auto constInt = dynamic_cast<ConstInt *>(child->val)) {
                int v = -constInt->getVal();
                return module->newConstInt(v);
            }

            // 否则生成指令
            SingleInstruction * negInst = new SingleInstruction(module->getCurrentFunction(),
                                                                IRInstOperator::IRINST_OP_UNARY_MINUS_I,
                                                                child->val,
                                                                child->val->getType());
            exprNode->blockInsts.addInst(child->blockInsts);
            exprNode->blockInsts.addInst(negInst);
            return negInst;
        }

        // 普通表达式直接处理
        if (!ir_visit_ast_node(exprNode)) {
            return nullptr;
        }
        return exprNode->val;
    }

    // 尝试将 AST 表达式静态求值为 Constant*
    Constant * evalConstExpr(ast_node * expr)
    {
        if (expr->node_type == ast_operator_type::AST_OP_LEAF_LITERAL_UINT) {
            // 假设 val 已经是 Constant*
            return static_cast<Constant *>(expr->val);
        } else if (expr->node_type == ast_operator_type::AST_OP_UNARY_MINUS) {
            Constant * child = evalConstExpr(expr->sons[0]);
            if (!child)
                return nullptr;
            int val = static_cast<ConstInt *>(child)->getVal();
            return module->newConstInt(-val);
        } else if (expr->node_type == ast_operator_type::AST_OP_UNARY_PLUS) {
            Constant * child = evalConstExpr(expr->sons[0]);
            if (!child)
                return nullptr;
            int val = static_cast<ConstInt *>(child)->getVal();
            return module->newConstInt(val);
        } else if (expr->node_type == ast_operator_type::AST_OP_UNARY_NOT) {
            Constant * child = evalConstExpr(expr->sons[0]);
            if (!child)
                return nullptr;
            int val = static_cast<ConstInt *>(child)->getVal();
            return module->newConstInt(!val);
        }
        // 可拓展更多操作符，如加减乘除等
        return nullptr;
    }

protected:
    /// @brief 编译单元AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_compile_unit(ast_node * node);

    /// @brief 函数定义AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_function_define(ast_node * node);

    /// @brief 形式参数AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_function_formal_params(ast_node * node);

    /// @brief 函数调用AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_function_call(ast_node * node);

    /// @brief 语句块（含函数体）AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_block(ast_node * node);

    /// @brief 整数加法AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_add(ast_node * node);

    /// @brief 整数减法AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_sub(ast_node * node);

    /// @brief 整数乘法AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_mul(ast_node * node);

    /// @brief 整数取余AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_mod(ast_node * node);

    /// @brief 整数除法AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_div(ast_node * node);

    /// @brief 关系运算符AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_less(ast_node * node);
    bool ir_greater(ast_node * node);
    bool ir_less_equal(ast_node * node);
    bool ir_greater_equal(ast_node * node);
    bool ir_eq(ast_node * node);
    bool ir_neq(ast_node * node);

    /// @brief 逻辑运算符AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_land(ast_node * node);
    bool ir_land(ast_node * node, LabelInstruction * true_label, LabelInstruction * false_label);
    bool ir_lor(ast_node * node);
    bool ir_lor(ast_node * node, LabelInstruction * true_label, LabelInstruction * false_label);
    bool ir_lnot(ast_node * node);

    /// @brief 一元运算符AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_unary_minus(ast_node * node);
    bool ir_unary_plus(ast_node * node);

    /// @brief 赋值AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_assign(ast_node * node);

    /// @brief 变量初始化赋值AST节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_init(ast_node * node1);

    /// @brief return节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_return(ast_node * node);

    /// @brief if节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_if(ast_node * node);

    /// @brief else节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_else(ast_node * node);

    /// @brief 类型叶子节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_leaf_node_type(ast_node * node);

    /// @brief 标识符叶子节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_leaf_node_var_id(ast_node * node);

    /// @brief 无符号整数字面量叶子节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_leaf_node_uint(ast_node * node);

    /// @brief float数字面量叶子节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_leaf_node_float(ast_node * node);

    /// @brief 变量声明语句节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_declare_statment(ast_node * node);

    /// @brief 变量定声明节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_variable_declare(ast_node * node);

    /// @brief 常量声明语句节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_const_decl(ast_node * node);

    /// @brief 常量定义节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_const_def(ast_node * node);

    /// @brief 宏定义声明节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_define_decl(ast_node * node);

    /// @brief define宏定义节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_define(ast_node * node);

    /// @brief 未知节点类型的节点处理
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_default(ast_node * node);

    /// @brief while节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_while(ast_node * node);

    /// @brief break节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_break(ast_node * node);

    /// @brief continue节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_continue(ast_node * node);

    /// @brief 数组声明节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_array_decl(ast_node * node);

    /// @brief 数组访问节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_array_access(ast_node * node);

    /// @brief 数组初始化节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true: 成功，false: 失败
    bool ir_array_init(ast_node * node);
    bool process_init_list(ast_node * initNode, PointerType * arrType, std::vector<Value *> & initValues);
    bool init_global_array(ast_node * array_decl, PointerType * arrType, const std::vector<Value *> & initValues);
    bool init_local_array(ast_node * array_decl, PointerType * arrType, const std::vector<Value *> & initValues);
    bool flatten_init_values(const std::vector<Value *> & values,
                             Type * expectedType,
                             int maxElements,
                             std::vector<Value *> & result);
    void calculate_array_indices(PointerType * arrType, int linearIndex, std::vector<Value *> & indices);

    /// @brief 类型转换节点翻译成线性中间IR
    /// @param node AST节点
    /// @return 翻译是否成功，true：成功，false：失败
    bool ir_cast(ast_node * node);

    // /// @brief 指针类型节点
    // bool ir_pointer_type(ast_node * node);

    /// @brief 根据AST的节点运算符查找对应的翻译函数并执行翻译动作
    /// @param node AST节点
    /// @return 成功返回node节点，否则返回nullptr
    ast_node * ir_visit_ast_node(ast_node * node);

    /// @brief AST的节点操作函数
    typedef bool (IRGenerator::*ast2ir_handler_t)(ast_node *);

    /// @brief AST节点运算符与动作函数关联的映射表
    std::unordered_map<ast_operator_type, ast2ir_handler_t> ast2ir_handlers;

    /// @brief 用于存储循环出口标签的栈，主要为break语句服务
    std::vector<Instruction *> breakTargetLabels;

    /// @brief 用于存储循环条件判断标签的栈，主要为continue语句服务
    std::vector<Instruction *> continueTargetLabels;

    int ir_constint_ast_node(ast_node * node);

    float ir_constfloat_ast_node(ast_node * node);

    Value * convertToBool(ast_node * node, Value * val, InterCode & code);

    /// @brief 评估常量表达式，如果不是常量表达式则返回nullptr
    /// @param node AST节点
    /// @return 常量值，如果不是常量表达式则返回nullptr
    Constant * evalConstExpr1(ast_node * node);

    /// @brief 折叠常量加法
    Constant * foldConstantAdd(Constant * left, Constant * right);

    /// @brief 折叠常量减法
    Constant * foldConstantSub(Constant * left, Constant * right);

    /// @brief 折叠常量乘法
    Constant * foldConstantMul(Constant * left, Constant * right);

    /// @brief 折叠常量除法
    Constant * foldConstantDiv(Constant * left, Constant * right);

    /// @brief 折叠常量取模
    Constant * foldConstantMod(Constant * left, Constant * right);

    /// @brief 折叠常量取负
    Constant * foldConstantNeg(Constant * operand);

private:
    /// @brief 抽象语法树的根
    ast_node * root;

    /// @brief 符号表:模块
    Module * module;
};
